home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / nhclb120.zoo / ax_mbx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  47.0 KB  |  1,924 lines

  1. /* Ok, I admit it... what I've done here is a mortal sin, but the XOBBS module
  2.    for ax_mbx.c is so different from the W9NK mailbox, and I hate forcing folks
  3.    to move files around before running a make, so here it is... the two cat'ed
  4.    together with an "if XOBBS ... else ... endif" wrapper... sick, but it
  5.    works...   Bdale */
  6.  
  7.  
  8. static domboxdisplay();
  9. static void free_mbx();
  10. static mbx_line();
  11. static mbx_msg();
  12. static mbx_to();
  13. static mbx_data();
  14. static void mbx_disc();
  15. void fwdxmit();
  16. void fwdrecv();
  17. void fwdstate();
  18. void axbbs_xmit();
  19. char xogetc();
  20.  
  21.  
  22. #ifdef XOBBS
  23. /* XOBBS.C  module to link NET thru IPC message queues to the XOBBS mailbox. */
  24. /* Jim Durham, W2XO, 1-5-89 */
  25. /* requires a call to axchk() to be inserted in the main commutator loop of
  26.     the net main.c code */
  27.  
  28. #include <stdio.h>
  29. #include "global.h"
  30. #include "config.h"
  31. #include "mbuf.h"
  32. #include "ax25.h"
  33. #include "timer.h"
  34. #include "lapb.h"
  35. #include "cmdparse.h"
  36. #include "iface.h"
  37. #include <fcntl.h>
  38. #include <signal.h>
  39. #include <sys/types.h>
  40. #include <sys/ipc.h>
  41. #include <sys/msg.h>
  42. #include "netrom.h"
  43. #include "nr4.h"
  44. #include "ax_mbx.h"
  45. #ifdef    UNIX
  46. #undef    toupper
  47. #undef    tolower
  48. #include <memory.h>
  49. #include <string.h>
  50. #endif
  51.  
  52. #ifdef    BSD
  53. char *sprintf();
  54. #endif
  55.  
  56. /*#define DEBUG       1*/
  57.  
  58. static char conbuf[10][10];        /*buffers used in getcon() and fwdcon()*/
  59. int conindex,conchar;
  60. int fwdflag;            /*flag to do various forwarding tasks*/
  61. int pid;
  62. int fwdbbsstate = NOCON;    /* con/discon state of forwarding bbs process */
  63. int smsgqid;            /* send message queue (from viewpoint of bbs) */
  64. int rmsgqid;            /* receive message queue (from viewpoint of bbs) */
  65. int scmsgqid;            /* send CONTROL message queue */
  66. int rcmsgqid;            /* receive CONTROL message queue */
  67. int lastindex;                  /*last bbs index used*/
  68. int nsend;
  69. int ax25mbox;
  70. char temp[128];
  71. char *bbsexe = "xobbs";        /*path to bbs executable*/
  72. struct  ax25_cb *bbscb;        /*forwarding bbs control block*/
  73. struct message  msg;
  74.  
  75. struct mboxsess * base = NULLMBS;  /*pointer to base of mailbox chain*/
  76. struct mboxsess fwdstruct;    /*forwarding session*/
  77.  
  78. #ifdef SID2
  79. extern struct ax25_addr bbscall;
  80. #endif
  81.  
  82. static struct mboxsess *
  83. newmbox()
  84. {
  85.     struct mboxsess * mbp ;
  86.  
  87.         if(base == NULLMBS){
  88.             base =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  89.             base->next = NULLMBS;
  90.         initmbox(base);
  91.             return base;
  92.         }
  93.         else{
  94.         mbp = base;
  95.         while(mbp->next != NULLMBS)       /*go up the chain to the top*/
  96.             mbp = mbp->next;
  97.         mbp->next =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  98.         mbp->next->next = NULLMBS;
  99.         initmbox(mbp->next);
  100.         return mbp->next;
  101.     }
  102. }
  103.  
  104. initmbox(mbp)
  105.     struct mboxsess * mbp;
  106. {
  107.     
  108.     mbp->bytes = 0;
  109.     mbp->gotbytes = 0;
  110.     mbp->mtxtptr = mbp->rmsgbuf.mtext;
  111. }
  112.  
  113. freembox(mbp)
  114.     struct mboxsess * mbp;
  115. {
  116.     struct mboxsess *p;
  117.     
  118.     if(mbp == base){            /*special case for base session*/
  119.         if(base->next != NULLMBS)/*if base is NOT the only session*/
  120.             base = base->next;   /*then make base point to next session*/
  121.         else
  122.             base = NULLMBS;     /*otherwise,just set base to NULLMBS*/
  123.         free(mbp);              /*free up the storage*/
  124.         return;                 /*and go away*/
  125.     }
  126.     p = base;
  127.     for(;;){
  128.         if(p->next == mbp){     /*if the next upward session is THE one*/
  129.             p->next = mbp->next; /*eliminate the next upward session*/
  130.             free(mbp);
  131.             return;
  132.         }
  133.         if(p->next == NULLMBS){ /*something is wrong here!*/
  134.             free(mbp);          /*try to fix it*/
  135.             return;
  136.         }
  137.         p = p->next;
  138.     }
  139. }
  140.     
  141.             
  142. axchk()        /* service any ax25 connections w2xo 9-1-88*/
  143. {
  144.     int rdcnt;
  145.     struct mbuf *bp;
  146.     struct mboxsess * mbp;
  147.     char *cp;
  148.     int testsize,size;
  149.     void axinit();
  150.     
  151. /* initialization code removed.  call to axinit() direct from main now. */
  152.     
  153.     if(base == NULLMBS)                       /*no mailboxes?..then leave*/
  154.         goto fcontchk;
  155.     mbp = base;                    /*point to the session base*/
  156.     while(mbp != NULLMBS){            /*and climb the session links*/
  157.         if(mbp->gotbytes < 1)            /*if we need input*/
  158.             if((mbp->gotbytes=msgrcv(smsgqid,&mbp->rmsgbuf,1024,(long)mbp->pid,
  159.                IPC_NOWAIT|0600)) < 1)        /*and there is none, ..punt*/
  160.                  goto contchk;
  161.             else                /*got input!*/
  162.                 mbp->mtxtptr = mbp->rmsgbuf.mtext; /*new message buffer, set to start*/
  163.  
  164.             testsize = min(mbp->bytes,mbp->cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  165.             size = min(testsize, mbp->gotbytes) + 1;       /* of bytes avail and paclen*/
  166.             bp = alloc_mbuf((int16)size);                  /* then min of avail and have*/
  167.             cp = bp->data;
  168.         if(mbp->proto == AX25){
  169.                 *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  170.                 bp->cnt =1;
  171.             }
  172.             else  bp->cnt = 0;
  173.             
  174.             while(bp->cnt < size && mbp->gotbytes){
  175.                 *cp++ = *mbp->mtxtptr++;
  176.                 bp->cnt++;
  177.                 mbp->gotbytes--;
  178.             }
  179.  
  180.         if(mbp->proto == AX25)
  181.             send_ax25(mbp->cbadr.axbbscb,bp);
  182.         else
  183.             send_nr4(mbp->cbadr.axnrcb,bp);
  184.                 /*now, check for control messages*/
  185.  
  186. contchk:    rdcnt=msgrcv(scmsgqid,&msg,1024,(long)mbp->pid,IPC_NOWAIT|0600);
  187. #ifdef DEBUG
  188.         if(rdcnt > 0) printf("net:Control Message received: rdcnt=%d\n",rdcnt);
  189. #endif
  190.             switch(rdcnt){
  191.                 case 0:     break;
  192.                 case -1:    /*perror("axchk002");*/
  193.                             break;
  194.                 default:    if(msg.mtext[0] == 'K'){
  195. #ifdef DEBUG
  196.                     printf("recbbs: K received\n");
  197. #endif
  198.                 kill(mbp->pid,9);
  199.                 wait(NULLCHAR);
  200.                 clearque(mbp->pid);
  201.                  if(mbp->proto == AX25)
  202.                      disc_ax25(mbp->cbadr.axbbscb);
  203.                  else
  204.                      disc_nr4(mbp->cbadr.axnrcb);
  205.  
  206.                 freembox(mbp);
  207.                             }/* if K */
  208.             }/* switch */
  209.         mbp = mbp->next;
  210.     }/*while loop*/
  211.  
  212. fcontchk:    chkfwd();            /*check the forwarder*/
  213. }
  214.  
  215. dombox(argc, argv)
  216. int argc ;
  217. char *argv[] ;
  218. {
  219.     if (argc < 2) {
  220.         domboxdisplay() ;
  221.         return 0 ;
  222.     }
  223.  
  224.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  225.         ax25mbox = 1 ;
  226.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  227.         ax25mbox = 0 ;
  228.     else if (argv[1][0] == '?')
  229.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  230.     else
  231.         printf("usage: mbox [y|n|?]\n") ;
  232.  
  233.     return 0 ;
  234. }
  235.  
  236. static domboxdisplay()
  237. {
  238.  
  239.     struct mboxsess * mbp;
  240.     printf("Process-ID     &cb      Protocol      User\n") ;
  241.         mbp = base;    
  242.     while(mbp != NULLMBS){
  243.             printf("%-13d%-13x",mbp->pid,mbp->cbadr.axbbscb);             
  244.                 if(mbp->proto == AX25)
  245.                 printf("Ax25        %s\n",mbp->call);
  246.             else
  247.                 printf("Net/Rom     %s\n",mbp->call);
  248.             mbp = mbp->next;
  249.         }/*while loop*/
  250.     printf("\n\n");
  251.     printf("Forwarder State is: ");
  252.     switch(fwdflag){
  253.       case 0: printf("NOFWD\n");
  254.               break;
  255.       case 1: printf("SPAWNBBS\n");
  256.               break;
  257.       case 2: printf("DOCONNECT\n");
  258.               break;
  259.       case 3: printf("READXMIT\n");
  260.               break;
  261.       case 4: printf("GETCON\n");
  262.               break;
  263.       case 5: printf("CLEARCON\n");
  264.               break;
  265.       case 6: printf("WAITING\n");
  266.               break;
  267.       default: printf("UNDEFINED\n");
  268.               break;
  269.     }
  270. }
  271. /* Incoming mailbox session via ax.25 */
  272.  
  273.  
  274. /* * This is the ax25 receive upcall function
  275.  *it gathers incoming data and stuff it down the IPC queue to the proper BBS
  276.  */
  277.  
  278. void
  279. mbx_incom(axp,cnt)    
  280. struct ax25_cb *axp;
  281. int16 cnt;
  282. {
  283. #ifndef SID2
  284.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  285.     void mbx_tx(), mbx_rx(), mbx_state();
  286.     int j;
  287.     struct mboxsess *mbp;
  288.     struct mbuf *bp;
  289.     struct mbuf *recv_ax25();
  290.     
  291.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  292.                         /* so, make a new mailbox session*/
  293.             axp->r_upcall = mbx_rx ;
  294.             axp->t_upcall = mbx_tx ;
  295.         axp->s_upcall = mbx_state;
  296.                 mbp->cbadr.axbbscb=axp;
  297.                 mbp->proto = AX25;
  298.                 mbp->bytes = 32;    /*jump start the upcall*/
  299.  
  300.         bp = recv_ax25(axp,cnt) ;    /* get the initial input */
  301.         free_p(bp) ;            /* and throw it away to avoid confusion */
  302.  
  303.  
  304.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  305.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  306.                     arg1[j]=arg1[j] >> 1;
  307.                     arg1[j]=arg1[j] & (char)0x7f;
  308.                     if(arg1[j]==' ') arg1[j]='\0';
  309.                 }
  310.                 arg1[6]='\0';            /*terminate call letters*/
  311.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  312.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  313.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  314.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  315.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  316.  
  317.                                            /*now, fork and exec the bbs*/
  318.                 if((pid=fork()) == 0){              /*if we are the child*/
  319.                     if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  320. #ifdef DEBUG
  321.                         printf("Bad exec on BBS\n");
  322. #endif
  323.                         exit(1);
  324.                     }
  325.                 }
  326.                 else                      /* parent process is still NET */
  327.                     mbp->pid=pid;         /* save pid of new baby*/
  328. #endif
  329. }    
  330.  
  331. void
  332. mbx_rx(axp,cnt)        /*w2xo  2-16-89  */
  333. struct ax25_cb *axp;        /* send chars down pipe to bbs */
  334. int16 cnt;
  335. {
  336.     struct mbuf *bp;
  337.     struct mbuf *recv_ax25();
  338.     struct mboxsess * mbp;
  339.  
  340.     
  341.     if(base == NULLMBS)
  342.         return;
  343.     mbp = base;
  344.     while(mbp != NULLMBS){
  345.     if(mbp->proto == AX25){
  346.             if(mbp->cbadr.axbbscb == axp){  /* match requested block? */
  347.                 if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  348.             continue;
  349.                 while(bp != NULLBUF){
  350.                     strncpy(msg.mtext,bp->data,bp->cnt);
  351.                     msg.mtype = (long)mbp->pid;
  352.                     if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  353.                         perror("axincoming");
  354.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  355.                 }
  356.             } /* if matching axp */
  357.         }/*if ax25 */
  358.     mbp = mbp->next;
  359.     }/*while loop*/
  360. }
  361.  
  362. void
  363. mbx_tx(axp,cnt)
  364. struct ax25_cb *axp;
  365. int16 cnt;
  366. {
  367.     struct mboxsess * mbp;
  368.     if(base == NULLMBS)
  369.         return;                     /*no sessions*/
  370.     mbp = base;
  371.     while(mbp != NULLMBS){
  372.         if(mbp->cbadr.axbbscb == axp)
  373.             mbp->bytes = cnt;
  374.     mbp = mbp->next;
  375.     }
  376. }
  377.  
  378. void
  379. mbx_state(axp,old,new)        /*w2xo  3-23-89 */
  380. struct ax25_cb *axp;
  381. int old,new;
  382. {
  383. #ifdef SID2
  384.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  385.     void mbx_tx(), mbx_rx(), mbx_state();
  386.     int j;
  387. #endif
  388.     struct mboxsess *mbp;
  389.  
  390.         switch(new){
  391.             case DISCONNECTED:
  392.            if((old == DISCONNECTED) || (old == DISCPENDING))
  393.                return;
  394.                 if(base == NULLMBS)
  395.                     break;
  396.             mbp = base;
  397.                 while(mbp != NULLMBS){
  398.                     if(axp == mbp->cbadr.axbbscb && mbp->proto == AX25){
  399.                         kill(mbp->pid,9);     /*kill bbs process*/
  400.                         wait(NULLCHAR);
  401.                         freembox(mbp);
  402.                         break; /* from while loop */
  403.                     } /*if*/
  404.                     mbp = mbp->next;
  405.                 }/*while loop*/
  406.                 break;   /*end of DISCONNECTED case*/
  407.                     
  408.             case CONNECTED:
  409. #ifdef SID2
  410.         if(old != DISCONNECTED)
  411.             return;
  412.             if(!calleq(axp,&bbscall)){ /*not for the mailbox*/
  413.             axp->s_upcall = NULLVFP;
  414.             return;
  415.             }
  416.     
  417.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  418.                         /* so, make a new mailbox session*/
  419.             axp->r_upcall = mbx_rx ;
  420.             axp->t_upcall = mbx_tx ;
  421.  
  422.                 mbp->cbadr.axbbscb=axp;
  423.                 mbp->proto = AX25;
  424.                 mbp->bytes = 32;    /*jump start the upcall*/
  425.  
  426.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  427.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  428.                     arg1[j]=arg1[j] >> 1;
  429.                     arg1[j]=arg1[j] & (char)0x7f;
  430.                     if(arg1[j]==' ') arg1[j]='\0';
  431.                 }
  432.                 arg1[6]='\0';            /*terminate call letters*/
  433.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  434.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  435.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  436.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  437.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  438.  
  439.                                            /*now, fork and exec the bbs*/
  440.                 if((pid=fork()) == 0){              /*if we are the child*/
  441.                     if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  442. #ifdef DEBUG
  443.                         printf("Bad exec on BBS\n");
  444. #endif
  445.                         exit(1);
  446.                     }
  447.                 }
  448.                 else                      /* parent process is still NET */
  449.                     mbp->pid=pid;         /* save pid of new baby*/
  450. #endif
  451.                 break;
  452.         }/* end of switch*/
  453. }/*end of routine*/
  454.  
  455.  
  456. /* Incoming mailbox session via net/rom */
  457.  
  458. void
  459. mbx_nr4incom(cb)
  460. register struct nr4cb *cb ;
  461. {
  462.     void mbx_nr4tx(), mbx_nr4rx(), mbx_nr4state() ;
  463.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];
  464.         struct mboxsess * mbp;
  465.     int j;
  466.         
  467.         mbp = newmbox();
  468.  
  469.     cb->r_upcall = mbx_nr4rx ;
  470.     cb->s_upcall = mbx_nr4state ;
  471.     cb->t_upcall = mbx_nr4tx ;
  472.  
  473.         mbp->cbadr.axnrcb = cb;
  474.         mbp->proto = NTRM;
  475.         mbp->bytes = 32;    /*jump start the upcall*/
  476.  
  477.         for(j=0;j<6;j++){               /*now, get incoming call letters*/
  478.             arg1[j]=mbp->cbadr.axnrcb->user.call[j];
  479.             arg1[j]=arg1[j] >> 1;
  480.             arg1[j]=arg1[j] & (char)0x7f;
  481.             if(arg1[j]==' ') arg1[j]='\0';
  482.         }
  483.         arg1[6]='\0';            /*terminate call letters*/
  484.     strcpy(mbp->call,arg1);  /*copy call to session*/
  485.  
  486.         sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  487.         sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  488.         sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  489.         sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  490.  
  491.                                          /*now, fork and exec the bbs*/
  492.         if((pid=fork()) == 0){              /*if we are the child*/
  493.             if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  494. #ifdef DEBUG
  495.                 printf("Bad exec on BBS\n");
  496. #endif
  497.                 exit(1);
  498.             }
  499.         }
  500.         else                            /* parent process is still NET */
  501.             mbp->pid=pid;         /* save pid of new baby*/
  502. }
  503.  
  504. /* receive upcall for net/rom */
  505. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  506. /* If the lines get too long, it arbitrarily breaks them. */
  507.  
  508. void mbx_nr4rx(cb,cnt)
  509. struct nr4cb *cb ;
  510. int16 cnt ;
  511. {
  512.     struct mbuf *bp;
  513.     struct mbuf *recv_ax25();
  514.     struct mboxsess * mbp;
  515.  
  516.  
  517.     
  518.     if(base == NULLMBS)
  519.         return;
  520.     mbp = base;
  521.     while(mbp != NULLMBS){
  522.     if(mbp->proto == NTRM){
  523.             if(mbp->cbadr.axnrcb == cb){  /* match requested block? */
  524.                 if((bp = recv_nr4(cb,cnt)) == NULLBUF)  /*nothing there*/
  525.             continue;
  526.                 while(bp != NULLBUF){
  527.                     strncpy(msg.mtext,bp->data,bp->cnt);
  528.                     msg.mtype = (long)mbp->pid;
  529.                     if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  530.                         perror("nrincoming");
  531.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  532.                 }
  533.             } /* if matching axp */
  534.         } /* if netrom */
  535.     mbp = mbp->next;
  536.     } /*while loop*/
  537. }
  538.  
  539. void
  540. mbx_nr4tx(cb,cnt)
  541. struct nr4cb *cb;
  542. int16 cnt;
  543. {
  544.     struct mboxsess *mbp;
  545.     if(base == NULLMBS)
  546.         return;
  547.     mbp = base;
  548.     while(mbp != NULLMBS){
  549.         if(mbp->cbadr.axnrcb == cb)
  550.             mbp->bytes = cnt;
  551.         mbp = mbp->next;
  552.     }
  553. }
  554.  
  555. /* state upcall for net/rom */
  556. void mbx_nr4state(cb,old,new)
  557. struct nr4cb *cb ;
  558. int old, new ;
  559. {
  560.     struct mboxsess * mbp;
  561.  
  562.     switch(new){
  563.         case DISCONNECTED:
  564.             if(base == NULLMBS)
  565.                 return;
  566.             mbp = base;
  567.             while(mbp != NULLMBS){
  568.                 if(cb == mbp->cbadr.axnrcb){
  569.                     kill(mbp->pid,9);     /*kill bbs process*/
  570.                     wait(NULLCHAR);
  571.                     freembox(mbp);
  572.                     break; /* from for loop */
  573.                 }
  574.             mbp = mbp->next;
  575.             }/*end of while loop*/
  576.         break;   /*end of DISCONNECTED case*/
  577.                     
  578.         case CONNECTED:
  579.             break; /* end of connected case*/
  580.     }/* end of switch*/
  581. }/*end of routine*/
  582.  
  583. indexx(s,t)
  584. char s[],t[];
  585. {
  586.     int i,j,k;
  587.     
  588.     for(i=0;s[i]!= '\0'; i++){
  589.         for(j=i,k=0;t[k]!='\0' && s[j] == t[k]; j++,k++)
  590.             ;
  591.         if(t[k] == '\0')
  592.             return(i);
  593.     }
  594.     return(-1);
  595. }
  596.  
  597.  
  598. chkfwd()                /* check forwarding and take appropriate*/
  599. {                    /* actions*/
  600.     int gotbytes;
  601.  
  602.     if(fwdbbsstate==WAIT)
  603.         return;
  604.     switch(fwdflag){
  605.         case NOFWD:     /* check for forward request */
  606.           if(msgrcv(scmsgqid,&msg,1024,1L,IPC_NOWAIT|0600) > 0) {
  607.               switch(msg.mtext[0]){
  608.               case 'F': fwdflag = SPAWNBBS;  /* forwarding request */
  609.                     break;
  610.               case 'B': sendbeac();
  611.                     break;
  612.               default:  break;
  613.               }
  614.           }
  615.           break;
  616.         case SPAWNBBS:  spawnfwd();
  617.                         nsend = false;
  618.                         break;
  619.         case DOCONNECT: fwdcon();
  620.                         break;
  621.         case READXMIT : fwdsend();
  622.                         break;
  623.         case GETCON:    getcon();
  624.                         break;
  625.         case CLEARCON:  clearcon(nsend);
  626.                 if(!(nsend))    /* only do clearcon without N once*/
  627.                     nsend = true;
  628.                         break;
  629.         case WAITING:   break;
  630.         default: break;
  631.     }
  632.     if(fwdflag != NOFWD){ /*if forwarder, check for control*/
  633.         gotbytes = msgrcv(scmsgqid,&msg,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);
  634.         switch(gotbytes){
  635.             case 0:     break;
  636.             case -1:    /*perror("axchk003");*/
  637.                         break;
  638.             default:    if(msg.mtext[0] == 'K'){
  639.                         kill(fwdstruct.pid,9);
  640.                         wait(NULLCHAR);
  641. #ifdef DEBUG
  642.             printf("clearing ques\n");
  643. #endif
  644.                         clearque(fwdstruct.pid);
  645.             fwdflag = NOFWD;
  646.             disc_ax25(fwdstruct.cbadr.axbbscb);
  647.                     fwdstruct.cbadr.axbbscb = NULLFWD;
  648.                         }
  649.                         else if(msg.mtext[0] == 'N'){
  650. #ifdef DEBUG
  651.                             printf("net:N received from BBS\n");
  652. #endif
  653.                             if(fwdbbsstate==YESCON){ /*if we are really connected*/
  654.                                 fwdbbsstate=WAIT;  /*wait until disconnect before next*/
  655.                                 disc_ax25(fwdstruct.cbadr.axbbscb); /*do the disconnect */
  656. #ifdef DEBUG
  657.                             printf("net:disconnect issued\n");
  658. #endif
  659.                             }
  660. #ifdef DEBUG
  661.                             printf("net:setting flag to CLEARCON\n");
  662. #endif
  663.                             fwdflag=CLEARCON;  /*set up for next connect*/
  664.                         }
  665.                         break;
  666.         } /*switch*/
  667.     } /* if forwarder active */
  668. }
  669.  
  670. spawnfwd()
  671. {
  672.     char arg1[20],arg2[20],arg3[20],arg4[20],arg5[20];
  673.  
  674.                   /*fork and exec the forwarder*/
  675.     if((fwdstruct.pid=fork()) == 0){              /* if this is the child*/
  676.         strcpy(arg1,"forward");
  677.         sprintf(arg2,"%d\0",rmsgqid);    /*tell the bbs what the message*/
  678.         sprintf(arg3,"%d\0",smsgqid);     /* que ids to use are*/
  679.         sprintf(arg4,"%d\0",rcmsgqid);
  680.         sprintf(arg5,"%d\0",scmsgqid);
  681.  
  682.             /*check for bad exec */
  683.         if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  684.         fprintf(stderr,"Bad Exec on forwarder\n");
  685.         exit(1);
  686.     }
  687.     }/* if fwdstruct.pid is 0 */
  688.     else{
  689.         fwdflag=CLEARCON;  /*not the child, so set flag for next level*/
  690.     fwdstruct.gotbytes = 0;
  691.     fwdstruct.bytes = 0;
  692.     fwdstruct.proto = AX25;
  693.     fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext;
  694.     }
  695. }
  696.     
  697. clearcon(nsend)
  698.     int nsend;
  699. {
  700.     int i;
  701.  
  702. #ifdef DEBUG
  703.     printf("net:clearcon:entering routine\n");
  704. #endif
  705.     for(i=0;i<10;i++)
  706.         conbuf[i][0]='\0';
  707. #ifdef DEBUG
  708.     printf("net:clearcon:Clearing ques\n");
  709. #endif
  710.     conindex=conchar=0;            /*clear the connect buffer*/
  711.     fwdflag=GETCON;
  712.     clearque(fwdstruct.pid);
  713.     if(nsend && fwdstruct.cbadr.axbbscb != NULLFWD){  /*don't send N to new bbs or no bbs */
  714.         msg.mtype = (long)fwdstruct.pid;
  715.     sprintf(msg.mtext,"N\0");
  716. #ifdef DEBUG
  717.         printf("net:Sending %s to bbs\n",msg.mtext);
  718. #endif
  719.         msgsnd(rcmsgqid,&msg,2,0600);
  720. #ifdef DEBUG
  721.         printf("net:clearcon:sent N to bbs process ID %d\n",fwdstruct.pid);
  722. #endif
  723.     }
  724. }
  725.     
  726.  
  727. getcon()                        /*routine called when fwdflag is "GETCON"*/
  728. {                               /* to read the connect request*/
  729.  
  730.     fwdstruct.gotbytes = msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);  /* is there anything in the pipe?*/
  731.     switch(fwdstruct.gotbytes){
  732.         case 0:     return;
  733.         case -1:    /*perror("getcon001");*/
  734.                     break;
  735.         default:    strncpy(conbuf[conindex],fwdstruct.rmsgbuf.mtext,fwdstruct.gotbytes);
  736.             if(fwdstruct.rmsgbuf.mtext[0] != 0x04){
  737.                         conbuf[conindex++][fwdstruct.gotbytes] = '\0';
  738.                         break;
  739.                    }
  740.                    else
  741.                    fwdflag = DOCONNECT;
  742.     }
  743.     fwdstruct.gotbytes=0;
  744. }
  745.  
  746. fwdcon()
  747. {
  748.     char *argv[10];
  749.  
  750.     char buf[128];
  751.     static char temp[] = "con";
  752.  
  753.     int numdigis;
  754.     int i;
  755.       
  756.     argv[1] = &conbuf[0][0];    /* get device to use*/
  757.     argv[2] = &conbuf[1][0];    /* get who to connect to*/
  758.     numdigis=atoi(&conbuf[2][0]);
  759.     for(i=0; i < numdigis;i++)
  760.         argv[3+i] = &conbuf[3+i][0];
  761.  
  762.     argv[0]= temp;              /* set up for the doconfwd() call */
  763.  
  764.     fflush(stdout);
  765.      if(!doconfwd(3+numdigis,argv)){               /*do the connect*/
  766.          sprintf(msg.mtext,"OK\n");
  767.          msg.mtype = (long)fwdstruct.pid;
  768.          if(msgsnd(rmsgqid,&msg,3,0600) < 0)
  769.              perror("fwdcon001");
  770.      fwdflag=WAITING;
  771.          return 0;
  772.      }
  773.      else{
  774.          sprintf(buf,"NOGOOD\n");
  775.      msg.mtype = (long)fwdstruct.pid;
  776.          if(msgsnd(rmsgqid,&msg,7,0600) < 0)
  777.              perror("fwdcon002");
  778.          fwdflag=CLEARCON;
  779.          return 1;
  780.     }
  781. }
  782.  
  783. void
  784. fwdstate(axp,old,new)        /*w2xo      10-24-88 */
  785. struct ax25_cb *axp;
  786. int old,new;
  787. {
  788.  
  789.  
  790.     switch(new){
  791.     case DISCONNECTED:  if(fwdflag==READXMIT){
  792.                 fwdflag=CLEARCON;
  793.                 }
  794.                 fwdbbsstate=NOCON;
  795.                 kill(fwdstruct.pid,SIGUSR1); /*tell bbs about discon*/
  796.                 break;
  797.                             
  798.     case CONNECTED:        fwdflag=READXMIT;
  799.                 fwdstruct.bytes = 32; /*jump start t_upcall*/
  800.                 fwdbbsstate=YESCON;
  801.                 break;
  802.         default:            break;
  803.     }
  804. }
  805.  
  806. void
  807. fwdxmit(axp,cnt)
  808. struct ax25_cb *axp;
  809. int16 cnt;
  810. {
  811.         /*all we want to do here is establish the max number of*/
  812.         /* bytes to send at any one time*/
  813.  
  814.     if(axp == fwdstruct.cbadr.axbbscb)
  815.         fwdstruct.bytes = cnt;
  816. }
  817.  
  818. void
  819. fwdrecv(axp,cnt)        /*w2xo  10-24-88  */
  820. struct ax25_cb *axp;        /* send chars down pipe to forwarding bbs */
  821. int16 cnt;
  822. {
  823.     struct mbuf *bp;
  824.     struct mbuf *recv_ax25();
  825.     
  826.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  827.         return;
  828.  
  829.     while(bp != NULLBUF){
  830.         strncpy(msg.mtext,bp->data,bp->cnt);
  831.     msg.mtype = (long)fwdstruct.pid;
  832.         if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  833.             perror("fwdrecv");
  834.         bp=free_mbuf(bp);
  835.     }
  836. }
  837.  
  838. fwdsend()        /* service bbs ax25 connections w2xo 10-24-88*/
  839. {
  840.     int size,testsize;
  841.     struct mbuf *bp;
  842.     char *cp;
  843.  
  844.     if(fwdstruct.cbadr.axbbscb != NULLFWD){
  845.         if(fwdstruct.gotbytes < 1)
  846.             if((fwdstruct.gotbytes=msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,
  847.                IPC_NOWAIT|0600)) < 1)
  848.                  return;   /*return if nothing to send*/
  849.             else
  850.                 fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext; /*new message buffer, set to start*/
  851.  
  852.         testsize = min(fwdstruct.bytes,fwdstruct.cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  853.         size = min(testsize, fwdstruct.gotbytes) +1;       /* of bytes avail and paclen*/
  854.         bp = alloc_mbuf((int16)size);                  /* then min of avail and have*/
  855.         cp = bp->data;
  856.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  857.         bp->cnt = 1;
  858.         while(bp->cnt < size){
  859.             *cp++ = *fwdstruct.mtxtptr++;
  860.             bp->cnt++;
  861.             fwdstruct.gotbytes--;
  862.         }
  863.         send_ax25(fwdstruct.cbadr.axbbscb,bp);
  864.     } /*if active */
  865. }
  866.  
  867. /* Initiate AX.25 forwarding connection to remote bbs */
  868. doconfwd(argc,argv)
  869. int argc;
  870. char **argv;
  871.  {
  872.     void fwdrecv(),fwdxmit(),fwdstate();
  873.     struct ax25_addr dest;
  874.     struct ax25 addr;
  875.     struct ax25_cb *open_ax25();
  876.     struct interface *ifp;
  877.     struct mboxsess *mbp;
  878.     extern int16 axwindow;
  879.     int i;
  880.  
  881.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  882.         if(strcmp(argv[1],ifp->name) == 0)
  883.             break;
  884.     if(ifp == NULLIF){
  885.         printf("Interface %s unknown\n",argv[1]);
  886.         return 1;
  887.     }
  888.  
  889.     mbp = base;            /* point to the session base */
  890.     while (mbp != NULLMBS) {    /* and climb the session */
  891.         if (!strncmp(mbp->call,argv[2],strlen(mbp->call)))
  892.             return 1;
  893.         mbp = mbp->next;    /* bomb out if session to this bbs */
  894.     }                /* exists */
  895.  
  896.     setcall(&dest,argv[2]);
  897. #ifndef NETROM
  898.     ASSIGN(addr.source,mycall);
  899. #else
  900.     memcpy(&addr.source,ifp->hwaddr,AXALEN);
  901. #endif
  902.     setcall(&addr.dest,argv[2]);
  903.     for(i=3; i < argc; i++)
  904.         setcall(&addr.digis[i-3],argv[i]);
  905.  
  906.     addr.ndigis = i - 3;
  907.     fwdstruct.cbadr.axbbscb = open_ax25(&addr,axwindow,fwdrecv,fwdxmit,fwdstate,ifp,(char *)0);
  908.     return 0;
  909. }
  910.  
  911.  
  912. fgetline(fd,s)
  913.     int fd;
  914.     char *s;
  915. {
  916.     int i;
  917.     char c;
  918.     i=0;
  919.     while((c=xogetc(fd)) && ((c != '\n') && (c != '\r')))
  920.         s[i++] = c;
  921.  
  922.     s[i] = '\0';
  923.     return(i);
  924. }
  925.  
  926.  
  927. char xogetc(fd)
  928. {
  929.     char c;
  930.     if(read(fd,&c,1)){
  931.         c &= (char)0x7f;        /*strip 8th bit and up*/
  932.         if(c=='\r')
  933.             c='\n';
  934.         return(c);
  935.     }
  936.     else return('\0');
  937. }
  938.  
  939.  
  940. void
  941. axinit()
  942. {
  943.     int fd;
  944.  
  945.     if((smsgqid=msgget(SENDKEY,IPC_CREAT|0600)) < 0){
  946.         perror("msgget smsgqid:");
  947.         exit(1);
  948.     }
  949.     else
  950.         printf("Send message que identifier is:%d\n",smsgqid);
  951.         
  952.     if((rmsgqid=msgget(RCVKEY,IPC_CREAT|0600)) < 0){
  953.         perror("msgget rmsgqid:");
  954.         exit(1);
  955.     }
  956.     else
  957.         printf("Receive message que identifier is:%d\n",rmsgqid);
  958.  
  959.     if((scmsgqid=msgget(SCTLKEY,IPC_CREAT|0600)) < 0){
  960.         perror("msgget scmsgqid:");
  961.         exit(1);
  962.     }
  963.     else {
  964.         printf("Control send message que identifier is:%d\n",scmsgqid);
  965.     }
  966.  
  967.     if((rcmsgqid=msgget(RCTLKEY,IPC_CREAT|0600)) < 0){
  968.         perror("msgget rcmsgqid:");
  969.         exit(1);
  970.     }
  971.     else
  972.         printf("Control receive message que identifier is:%d\n",rcmsgqid);
  973.  
  974. }
  975.  
  976. clearque(pid)
  977.     int pid;
  978. {
  979.     while(msgrcv(smsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  980.         ;
  981.     while(msgrcv(rmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  982.         ;
  983.     while(msgrcv(scmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  984.         ;
  985.     while(msgrcv(rcmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  986.         ;
  987. }
  988.  
  989. calleq(axp,addr)
  990.     struct ax25_cb *axp;
  991.     struct ax25_addr *addr;
  992. {
  993.     register int i;
  994.  
  995.     if(memcmp(axp->addr.source.call,addr->call,ALEN) != 0)
  996.         return 0;
  997.     if((axp->addr.source.ssid & SSID) != (addr->ssid & SSID))
  998.         return 0;
  999.     return 1;
  1000. }
  1001.  
  1002. sendbeac()
  1003. {
  1004.     int gotbytes;
  1005.     struct mbuf *bp;
  1006.     char *cp,*kp;
  1007.     struct interface *iface;
  1008.         extern struct interface *ifaces;
  1009.                 
  1010.     if((gotbytes = msgrcv(smsgqid,&msg,1024,(long)2,0600)) < 0){
  1011.         perror("sendbeac:receiving message");
  1012.         return;
  1013.     }
  1014.     
  1015.     for(iface = ifaces; iface->next != NULLIF ; iface = iface->next){
  1016.         if((iface->name[0] != 'a') || (iface->name[1] != 'x'))
  1017.             continue;
  1018.             bp = alloc_mbuf((int16)(gotbytes + 2));                  /* then min of avail and have*/
  1019.             cp = bp->data;
  1020.             kp = msg.mtext;
  1021.             *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  1022.             bp->cnt = 1;
  1023.             do{
  1024.                 *cp++ = *kp++;
  1025.                 bp->cnt++;
  1026.             }while(bp->cnt < (gotbytes + 1));
  1027.  
  1028. #ifdef SID2
  1029.         ax_output(iface,(char*)&ax25_bdcst,(char *)&bbscall,(PID_FIRST |PID_LAST|PID_NO_L3),bp);
  1030. #else
  1031.         ax_output(iface,(char*)&ax25_bdcst,(char *)mycall,(PID_FIRST |PID_LAST|PID_NO_L3),bp);
  1032. #endif
  1033.  
  1034.         }
  1035. }
  1036.  
  1037.  
  1038. #else /* not XOBBS */
  1039.  
  1040. #include <stdio.h>
  1041. #include <time.h>
  1042. #include <ctype.h>
  1043. #ifdef    UNIX
  1044. #ifdef    UNIX
  1045. #undef    toupper
  1046. #undef    tolower
  1047. #endif
  1048. #include <sys/types.h>
  1049. #endif
  1050. #include "global.h"
  1051. #include "mbuf.h"
  1052. #include "ax25.h"
  1053. #include "timer.h"
  1054. #include "iface.h"
  1055. #include "lapb.h"
  1056. #include "netrom.h"
  1057. #include "nr4.h"
  1058. #include "ax_mbx.h"
  1059. #include "cmdparse.h"
  1060. #ifdef    UNIX
  1061. #include <memory.h>
  1062. #include <string.h>
  1063. #endif
  1064.  
  1065. #ifdef    BSD
  1066. char *sprintf();
  1067. #endif
  1068.  
  1069. /*
  1070. #define MBDEBUG
  1071. */
  1072.  
  1073. struct mbx *mbox[NUMMBX] ;
  1074. int ax25mbox ;
  1075.  
  1076. static char mbbanner[] =
  1077.     "[NET-$]\rWelcome to the %s TCP/IP Mailbox\r(C)hat, (S)end, (B)ye >\r" ;
  1078. static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
  1079.  
  1080. dombox(argc, argv)
  1081. int argc ;
  1082. char *argv[] ;
  1083. {
  1084.     if (argc < 2) {
  1085.         domboxdisplay() ;
  1086.         return 0 ;
  1087.     }
  1088.  
  1089.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  1090.         ax25mbox = 1 ;
  1091.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  1092.         ax25mbox = 0 ;
  1093.     else if (argv[1][0] == '?')
  1094.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  1095.     else
  1096.         printf("usage: mbox [y|n|?]\n") ;
  1097.  
  1098.     return 0 ;
  1099. }
  1100.  
  1101. static domboxdisplay()
  1102. {
  1103.     int i ;
  1104.     struct mbx *m ;
  1105.     static char *states[] = {"NONE","CMD","SUBJ","DATA"} ;
  1106.     static char *mbtype[] = {"NONE","AX25 ","NET/ROM"} ;
  1107.     
  1108.     printf(" User     State    Type    &cb\n") ;
  1109.  
  1110.     for (i = 0 ; i < NUMMBX ; i++)
  1111.         if ((m = mbox[i]) != NULLMBX)
  1112.             printf("%10s %4s  %7s   %04x\n", m->name, states[m->state],
  1113.                     mbtype[m->type],
  1114.                     m->type == MBX_AX25 ? (int)m->cb.ax25_cb : (int)m->cb.nr4_cb) ;
  1115. }
  1116.  
  1117.     
  1118. static struct mbx *
  1119. newmbx()
  1120. {
  1121.     int i ;
  1122.     struct mbx *m ;
  1123.  
  1124.     for (i = 0 ; i < NUMMBX ; i++)
  1125.         if (mbox[i] == NULLMBX) {
  1126.             if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx)))
  1127.                 == NULLMBX)
  1128.                 return NULLMBX ;
  1129.             m->mbnum = i ;
  1130.             return m ;
  1131.         }
  1132.  
  1133.     /* If we get here, there are no free mailbox sessions */
  1134.  
  1135.     return NULLMBX ;
  1136. }
  1137.  
  1138.  
  1139. /* Incoming mailbox session via ax.25 */
  1140.  
  1141. void
  1142. mbx_incom(axp,cnt)
  1143. register struct ax25_cb *axp ;
  1144. int16 cnt ;
  1145. {
  1146.     struct mbx *m ;
  1147.     struct mbuf *bp, *recv_ax25() ;
  1148.     char *cp ;
  1149.     extern char hostname[] ;
  1150.     void mbx_rx(), mbx_state() ;
  1151.     extern char *index() ;
  1152.     
  1153.     if ((m = newmbx()) == NULLMBX) {
  1154.         disc_ax25(axp) ;    /* no memory! */
  1155.         return ;
  1156.     }
  1157.  
  1158.     m->state = MBX_CMD ;    /* start in command state */
  1159.     m->type = MBX_AX25 ;    /* this is an ax.25 mailbox session */
  1160.     m->cb.ax25_cb = axp ;
  1161.  
  1162.     pax25(m->name,&axp->addr.dest) ;
  1163.     cp = index(m->name,'-') ;
  1164.     if (cp != NULLCHAR)            /* get rid of SSID */
  1165.         *cp = '\0' ;
  1166.  
  1167.     m->lp = m->line ;        /* point line pointer at buffer */
  1168.     axp->r_upcall = mbx_rx ;
  1169.     axp->s_upcall = mbx_state ;
  1170.     axp->user = (char *)m ;
  1171.  
  1172.     /* The following is necessary because we didn't know we had a */
  1173.     /* "real" ax25 connection until a data packet came in.  We    */
  1174.     /* can't be spitting banners out at every station who connects, */
  1175.     /* since they might be a net/rom or IP station.  Sorry.  */
  1176.     
  1177.     bp = recv_ax25(axp,cnt) ;        /* get the initial input */
  1178.     free_p(bp) ;                    /* and throw it away to avoid confusion */
  1179.  
  1180.     /* Now say hi */
  1181.     
  1182.     if ((bp = alloc_mbuf((int16)(strlen(hostname) + strlen(mbbanner) + 2))) == NULLBUF) {
  1183.         disc_ax25(axp) ; /* mbx_state will fix stuff up */
  1184.         return ;
  1185.     }
  1186.  
  1187.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;    /* pid */
  1188.     (void)sprintf(bp->data+1,mbbanner,hostname) ;
  1189.     bp->cnt = strlen(bp->data+1) + 1 ;
  1190.  
  1191.     send_ax25(axp,bp) ;                    /* send greeting message and menu */
  1192. }
  1193.  
  1194. /* receive upcall for ax.25 */
  1195. /* mbx_rx collects lines, and calls mbx_line when they are complete. */
  1196. /* If the lines get too long, it arbitrarily breaks them. */
  1197.  
  1198. void mbx_rx(axp,cnt)
  1199. struct ax25_cb *axp ;
  1200. int16 cnt ;
  1201. {
  1202.     struct mbuf *bp, *recv_ax25() ;
  1203.     struct mbx *m ;
  1204.     char c ;
  1205.     int mbx_line() ;
  1206.     
  1207.     m = (struct mbx *)axp->user ;
  1208.     
  1209.     if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
  1210.         return ;
  1211.  
  1212.     while (pullup(&bp,&c,1) == 1) {
  1213.         if (c == '\r') {
  1214.             *m->lp = '\0' ;            /* null terminate */
  1215.             if (mbx_line(m) == -1) {    /* call the line processor */
  1216.                 free_p(bp) ;        /* toss the rest */
  1217.                 break ;                /* get out - we're obsolete */
  1218.             }
  1219.             m->lp = m->line ;        /* reset the pointer */
  1220.         }
  1221.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1222.             *m->lp++ = c ;
  1223.             *m->lp = '\0' ;
  1224.             if (mbx_line(m) == -1) {
  1225.                 free_p(bp) ;
  1226.                 break ;
  1227.             }
  1228.             m->lp = m->line ;
  1229.         }
  1230.         else
  1231.             *m->lp++ = c ;
  1232.     }
  1233. }
  1234.  
  1235. /* state upcall for ax.25 */
  1236.  
  1237. /*ARGSUSED*/
  1238. void mbx_state(axp,old,new)
  1239. struct ax25_cb *axp ;
  1240. int old, new ;
  1241. {
  1242.     struct mbx *m ;
  1243.     void free_mbx() ;
  1244.     
  1245.     m = (struct mbx *)axp->user ;
  1246.  
  1247.     /* dummy for now ... */
  1248.     if (new == DISCONNECTED) {
  1249.         axp->user = NULLCHAR ;
  1250.         free_mbx(m) ;
  1251.     }
  1252. }
  1253.  
  1254.  
  1255. /* Incoming mailbox session via net/rom */
  1256.  
  1257. void
  1258. mbx_nr4incom(cb)
  1259. register struct nr4cb *cb ;
  1260. {
  1261.     struct mbx *m ;
  1262.     struct mbuf *bp ;
  1263.     char *cp ;
  1264.     extern char hostname[] ;
  1265.     void mbx_nr4rx(), mbx_nr4state() ;
  1266.     extern char *index() ;
  1267.     
  1268.     if ((m = newmbx()) == NULLMBX) {
  1269.         disc_nr4(cb) ;    /* no memory! */
  1270.         return ;
  1271.     }
  1272.  
  1273.     m->state = MBX_CMD ;    /* start in command state */
  1274.     m->type = MBX_NETROM ;    /* mailbox session type is net/rom */
  1275.     m->cb.nr4_cb = cb ;
  1276.  
  1277.     pax25(m->name,&cb->user) ;
  1278.     cp = index(m->name,'-') ;
  1279.     if (cp != NULLCHAR)            /* get rid of SSID */
  1280.         *cp = '\0' ;
  1281.  
  1282.     m->lp = m->line ;        /* point line pointer at buffer */
  1283.     cb->r_upcall = mbx_nr4rx ;
  1284.     cb->s_upcall = mbx_nr4state ;
  1285.     cb->puser = (char *)m ;
  1286.  
  1287.     /* Say hi */
  1288.     
  1289.     if ((bp = alloc_mbuf((int16)(strlen(hostname) + strlen(mbbanner) + 1))) == NULLBUF) {
  1290.         disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
  1291.         return ;
  1292.     }
  1293.  
  1294.     (void)sprintf(bp->data,mbbanner,hostname) ;
  1295.     bp->cnt = strlen(bp->data) ;
  1296.  
  1297.     send_nr4(cb,bp) ;                    /* send greeting message and menu */
  1298. }
  1299.  
  1300. /* receive upcall for net/rom */
  1301. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  1302. /* If the lines get too long, it arbitrarily breaks them. */
  1303.  
  1304. void mbx_nr4rx(cb,cnt)
  1305. struct nr4cb *cb ;
  1306. int16 cnt ;
  1307. {
  1308.     struct mbuf *bp ;
  1309.     struct mbx *m ;
  1310.     char c ;
  1311.     int mbx_line() ;
  1312.     
  1313.     m = (struct mbx *)cb->puser ;
  1314.     
  1315.     if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
  1316.         return ;
  1317.  
  1318.     while (pullup(&bp,&c,1) == 1) {
  1319.         if (c == '\r') {
  1320.             *m->lp = '\0' ;            /* null terminate */
  1321.             if (mbx_line(m) == -1) {    /* call the line processor */
  1322.                 free_p(bp) ;        /* toss the rest */
  1323.                 break ;                /* get out - we're obsolete */
  1324.             }
  1325.             m->lp = m->line ;        /* reset the pointer */
  1326.         }
  1327.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1328.             *m->lp++ = c ;
  1329.             *m->lp = '\0' ;
  1330.             if (mbx_line(m) == -1) {
  1331.                 free_p(bp) ;
  1332.                 break ;
  1333.             }
  1334.             m->lp = m->line ;
  1335.         }
  1336.         else
  1337.             *m->lp++ = c ;
  1338.     }
  1339. }
  1340.  
  1341. /* state upcall for net/rom */
  1342.  
  1343. /*ARGSUSED*/
  1344. void mbx_nr4state(cb,old,new)
  1345. struct nr4cb *cb ;
  1346. int old, new ;
  1347. {
  1348.     struct mbx *m ;
  1349.     void free_mbx() ;
  1350.     
  1351.     m = (struct mbx *)cb->puser ;
  1352.  
  1353.     if (new == NR4STDISC) {
  1354.         cb->puser = NULLCHAR ;
  1355.         free_mbx(m) ;
  1356.     }
  1357. }
  1358.  
  1359. static void
  1360. free_mbx(m)
  1361. struct mbx *m ;
  1362. {
  1363.     if (m->to != NULLCHAR)
  1364.         free(m->to) ;
  1365.  
  1366.  
  1367.     if (m->tofrom != NULLCHAR)
  1368.         free(m->tofrom) ;
  1369.  
  1370.     if (m->tomsgid != NULLCHAR)
  1371.         free(m->tomsgid) ;
  1372.         
  1373.     if (m->tfile != NULLFILE)
  1374.         fclose(m->tfile) ;
  1375.  
  1376.     mbox[m->mbnum] = NULLMBX ;
  1377.     
  1378.     free(m) ;
  1379. }
  1380.  
  1381.  
  1382. static 
  1383. mbx_line(m)
  1384. struct mbx *m ;
  1385. {
  1386.     void ax_session(), nr4_session(), mbx_disc() ;
  1387.     char *host ;
  1388.     extern char hostname[] ;
  1389.     char fullfrom[80] ;
  1390.     
  1391.     if (m->state == MBX_CMD) {
  1392.         switch (tolower(m->line[0])) {
  1393.             case 'b':    /* bye - bye */
  1394.                 mbx_disc(m) ;
  1395.                 return -1 ;    /* tell line processor to quit */
  1396.                 break ;
  1397.             case 'c':    /* chat */
  1398.                 switch (m->type) {
  1399.                   case MBX_AX25:
  1400.                     m->cb.ax25_cb->user = NULLCHAR ;
  1401.                     ax_session(m->cb.ax25_cb,0) ;    /* make it a chat session */
  1402.                     break ;
  1403.                   case MBX_NETROM:
  1404.                     m->cb.nr4_cb->puser = NULLCHAR ;
  1405.                     nr4_session(m->cb.nr4_cb) ;
  1406.                     break ;
  1407.                 }
  1408.                 free_mbx(m) ;
  1409.                 return -1 ;
  1410.                 break ;
  1411.             case 's': {
  1412.                 int badsubj = 0 ;
  1413.  
  1414.                 /* Get S-command type (B,P,T, etc.) */
  1415.                 
  1416.                 if (m->line[1] == '\0')
  1417.                     m->stype = ' ' ;
  1418.                 else
  1419.                     m->stype = toupper(m->line[1]) ;
  1420.                     
  1421.                 if (mbx_to(m) == -1) {
  1422.                     if (m->sid & MBX_SID)
  1423.                         mbx_msg(m,"NO\r") ;
  1424.                     else {
  1425.                         mbx_msg(m,
  1426.                             "S command syntax error - format is:\r") ;
  1427.                         mbx_msg(m,
  1428.                           "  S name [@ host] [< from_addr] [$bulletin_id]\r") ;
  1429.                     }
  1430.                     badsubj++ ;
  1431.                 }
  1432.                 else if (validate_address(m->to) == 0)     {
  1433.                     if (m->sid & MBX_SID)
  1434.                         mbx_msg(m, "NO\r") ;
  1435.                     else
  1436.                         mbx_msg(m, "Bad user or host name\r") ;
  1437.                     free(m->to) ;
  1438.                     m->to = NULLCHAR ;
  1439.                     if (m->tofrom) {
  1440.                         free(m->tofrom) ;
  1441.                         m->tofrom = NULLCHAR ;
  1442.                     }
  1443.                     if (m->tomsgid) {
  1444.                         free(m->tomsgid) ;
  1445.                         m->tomsgid = NULLCHAR ;
  1446.                     }
  1447.                     badsubj++ ;
  1448.                 }
  1449.  
  1450.                 if (badsubj)
  1451.                     mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1452.                 else {
  1453.                     m->state = MBX_SUBJ ;
  1454.                     mbx_msg(m,    (m->sid & MBX_SID) ? "OK\r" : "Subject:\r") ;
  1455.                 }
  1456.                 break ;
  1457.             }
  1458.             case '[':    /* This is a BBS - say "OK", not "Subject:" */
  1459.               {
  1460.                 int len = strlen(m->line) ;
  1461.                 
  1462.                 if (m->line[len - 1] == ']') { /* must be an SID */
  1463.                     m->sid = MBX_SID ;
  1464.                     /* Now check to see if this is an RLI board. */
  1465.                     /* As usual, Hank does it a bit differently from */
  1466.                     /* the rest of the world. */
  1467.                     if (len >= 5)        /* [RLI] at a minimum */
  1468.                         if (strncmp(&m->line[1],"RLI",3) == 0)
  1469.                             m->sid |= MBX_SID_RLI ;
  1470.                     
  1471.                     mbx_msg(m,">\r") ;
  1472.                 }
  1473.               }
  1474.               break ;
  1475.             case 'f':
  1476.                 if (m->line[1] == '>' && (m->sid & MBX_SID)) {
  1477.                     /* RLI BBS' expect us to disconnect if we */
  1478.                     /* have no mail for them, which of course */
  1479.                     /* we don't, being rather haughty about our */
  1480.                     /* protocol superiority. */
  1481.                     if (m->sid & MBX_SID_RLI) {
  1482.                         mbx_disc(m) ;
  1483.                         return -1 ;
  1484.                     } else
  1485.                         mbx_msg(m,">\r") ;
  1486.                     break ;
  1487.                 }
  1488.                 /* Otherwise drop through to "huh?" */
  1489.             default:
  1490.                 mbx_msg(m,"Huh?\r") ;
  1491.                 mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1492.         }
  1493.     return 0 ;
  1494.     }
  1495.     else if (m->state == MBX_SUBJ) {
  1496.         if (mbx_data(m) == -1) {
  1497.             mbx_msg(m,"Can't create temp file for mail\r") ;
  1498.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1499.             free(m->to) ;
  1500.             m->to = NULLCHAR ;
  1501.             if (m->tofrom) {
  1502.                 free(m->tofrom) ;
  1503.                 m->tofrom = NULLCHAR ;
  1504.             }
  1505.             if (m->tomsgid) {
  1506.                 free(m->tomsgid) ;
  1507.                 m->tomsgid = NULLCHAR ;
  1508.             }
  1509.             m->state = MBX_CMD ;
  1510.             return 0 ;
  1511.         }
  1512.         m->state = MBX_DATA ;
  1513.         if ((m->sid & MBX_SID) == 0)
  1514.             mbx_msg(m,
  1515.               "Enter message.  Terminate with /EX or ^Z in first column:\r") ;
  1516.         return 0 ;
  1517.     }
  1518.     else if (m->state == MBX_DATA) {
  1519.         if (m->line[0] == 0x1a ||
  1520.             strcmp(m->line, "/ex") == 0 ||
  1521.             strcmp(m->line, "/EX") == 0) {
  1522.             if ((host = index(m->to,'@')) == NULLCHAR)
  1523.                 host = hostname ;        /* use our hostname */
  1524.             else
  1525.                 host++ ;                /* use the host part of address */
  1526.  
  1527.             /* make up full from name for work file */
  1528.             (void)sprintf(fullfrom,"%s@%s",m->name,hostname) ;
  1529.             
  1530.             fseek(m->tfile,0L,0) ;        /* reset to beginning */
  1531.             if (queuejob((struct tcb *)0,m->tfile,host,m->to,fullfrom) != 0)
  1532.                 mbx_msg(m,
  1533.                         "Couldn't queue message for delivery\r") ;
  1534.  
  1535.             free(m->to) ;
  1536.             m->to = NULLCHAR ;
  1537.             if (m->tofrom) {
  1538.                 free(m->tofrom) ;
  1539.                 m->tofrom = NULLCHAR ;
  1540.             }
  1541.             if (m->tomsgid) {
  1542.                 free(m->tomsgid) ;
  1543.                 m->tomsgid = NULLCHAR ;
  1544.             }
  1545.             fclose(m->tfile) ;
  1546.             m->tfile = NULLFILE ;
  1547.             m->state = MBX_CMD ;
  1548.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1549.             return 0 ;
  1550.         }
  1551.         /* not done yet! */
  1552.         fprintf(m->tfile,"%s\n",m->line) ;
  1553.         return 0 ;
  1554.     }
  1555.     return 0 ;
  1556. }
  1557.  
  1558. static
  1559. mbx_msg(m,msg)
  1560. struct mbx *m ;
  1561. char msg[] ;
  1562. {
  1563.     int len ;
  1564.     struct mbuf *bp ;
  1565.     struct ax25_cb *axp ;
  1566.     struct nr4cb *cb ;
  1567.  
  1568.     len = strlen(msg) ;
  1569.  
  1570.     switch (m->type) {
  1571.       case MBX_AX25:
  1572.         axp = m->cb.ax25_cb ;
  1573.             
  1574.         if ((bp = alloc_mbuf((int16)(len+1))) == NULLBUF) {
  1575.             disc_ax25(axp) ;
  1576.             return -1 ;
  1577.         }
  1578.  
  1579.         bp->cnt = len + 1 ;
  1580.     
  1581.         *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;
  1582.     
  1583.         memcpy(bp->data+1, msg, len) ;
  1584.  
  1585.         send_ax25(axp,bp) ;
  1586.  
  1587.         break ;
  1588.  
  1589.       case MBX_NETROM:
  1590.         cb = m->cb.nr4_cb ;
  1591.  
  1592.         if ((bp = alloc_mbuf((int16)len)) == NULLBUF) {
  1593.             disc_nr4(cb) ;
  1594.             return -1 ;
  1595.         }
  1596.  
  1597.         bp->cnt = len ;
  1598.  
  1599.         memcpy(bp->data, msg, len) ;
  1600.  
  1601.         send_nr4(cb, bp) ;
  1602.  
  1603.         break ;
  1604.     }
  1605.     return 0 ;
  1606. }
  1607.  
  1608.  
  1609. /* States for send line parser state machine */
  1610.  
  1611. #define        SKIP_CMD        1
  1612. #define        LOOK_FOR_USER    2
  1613. #define        IN_USER            3
  1614. #define        AFTER_USER        4
  1615. #define        LOOK_FOR_HOST    5
  1616. #define        IN_HOST            6
  1617. #define        AFTER_HOST        7
  1618. #define        LOOK_FOR_FROM    8
  1619. #define        IN_FROM            9
  1620. #define        AFTER_FROM        10
  1621. #define        LOOK_FOR_MSGID    11
  1622. #define        IN_MSGID        12
  1623. #define        FINAL_STATE        13
  1624. #define        ERROR_STATE        14
  1625.  
  1626. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  1627.  * return 0
  1628.  */
  1629. static
  1630. mbx_to(m)
  1631. struct mbx *m ;
  1632. {
  1633.     register char *cp ;
  1634.     int state ;
  1635.     char *user, *host, *from, *msgid ;
  1636.     int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
  1637.     
  1638.     cp = m->line ;
  1639.  
  1640.     for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
  1641. #ifdef MBDEBUG
  1642.         printf("State is %d, char is %c\n", state, *cp) ;
  1643. #endif
  1644.         switch (state) {
  1645.             case SKIP_CMD:
  1646.                 if (*cp == '\0')
  1647.                     state = ERROR_STATE ;        /* no user */
  1648.                 else if (isspace(*cp))
  1649.                     state = LOOK_FOR_USER ;
  1650.                 break ;
  1651.             case LOOK_FOR_USER:
  1652.                 if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
  1653.                     state = ERROR_STATE ;        /* no user */
  1654.                 else if (!isspace(*cp)) {        /* found start of user */
  1655.                     user = cp ;                    /* point at start */
  1656.                     userlen++ ;                    /* start counting */
  1657.                     state = IN_USER ;
  1658.                 }
  1659.                 break ;
  1660.             case IN_USER:
  1661.                 switch (*cp) {
  1662.                     case '\0':                    /* found username only */
  1663.                         state = FINAL_STATE ;
  1664.                         break ;
  1665.                     case '@':
  1666.                         state = LOOK_FOR_HOST ;    /* hostname should follow */
  1667.                         break ;
  1668.                     case '<':
  1669.                         state = LOOK_FOR_FROM ;    /* from name should follow */
  1670.                         break ;
  1671.                     case '$':
  1672.                         state = LOOK_FOR_MSGID ; /* message id should follow */
  1673.                         break ;
  1674.                     default:
  1675.                         if (isspace(*cp))
  1676.                             state = AFTER_USER ;    /* white space */
  1677.                         else
  1678.                             userlen++ ;                /* part of username */
  1679.                 }
  1680.                 break ;
  1681.             case AFTER_USER:
  1682.                 switch (*cp) {
  1683.                     case '\0':
  1684.                         state = FINAL_STATE ;        /* found username only */
  1685.                         break ;
  1686.                     case '@':
  1687.                         state = LOOK_FOR_HOST ;        /* hostname follows */
  1688.                         break ;
  1689.                     case '<':
  1690.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1691.                         break ;
  1692.                     case '$':
  1693.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1694.                         break ;
  1695.                     default:
  1696.                         if (!isspace(*cp))
  1697.                             state = ERROR_STATE ;
  1698.                 }
  1699.                 break ;
  1700.             case LOOK_FOR_HOST:
  1701.                 switch (*cp) {
  1702.                     case '\0':                    /* user@? */
  1703.                     case '@':                    /* user@@ */
  1704.                     case '<':                    /* user@< */
  1705.                     case '$':                    /* user@$ */
  1706.                         state = ERROR_STATE ;
  1707.                         break ;
  1708.                     default:
  1709.                         if (!isspace(*cp)) {
  1710.                             host = cp ;
  1711.                             hostlen++ ;
  1712.                             state = IN_HOST ;
  1713.                         }
  1714.                 }
  1715.                 break ;
  1716.             case IN_HOST:
  1717.                 switch (*cp) {
  1718.                     case '\0':
  1719.                         state = FINAL_STATE ;        /* found user@host */
  1720.                         break ;
  1721.                     case '@':
  1722.                         state = ERROR_STATE ;        /* user@host@? */
  1723.                         break ;
  1724.                     case '<':
  1725.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1726.                         break ;
  1727.                     case '$':
  1728.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1729.                         break ;
  1730.                     default:
  1731.                         if (isspace(*cp))
  1732.                             state = AFTER_HOST ;
  1733.                         else
  1734.                             hostlen++ ;
  1735.                 }
  1736.                 break ;
  1737.             case AFTER_HOST:
  1738.                 switch (*cp) {
  1739.                     case '\0':
  1740.                         state = FINAL_STATE ;        /* user@host */
  1741.                         break ;
  1742.                     case '@':
  1743.                         state = ERROR_STATE ;        /* user@host @ */
  1744.                         break ;
  1745.                     case '<':
  1746.                         state = LOOK_FOR_FROM ;        /* user@host < */
  1747.                         break ;
  1748.                     case '$':
  1749.                         state = LOOK_FOR_MSGID ;    /* user@host $ */
  1750.                         break ;
  1751.                     default:
  1752.                         if (!isspace(*cp))
  1753.                             state = ERROR_STATE ;    /* user@host foo */
  1754.                 }
  1755.                 break ;
  1756.             case LOOK_FOR_FROM:
  1757.                 switch (*cp) {
  1758.                     case '\0':                    /* user@host <? */
  1759.                     case '@':                    /* user@host <@ */
  1760.                     case '<':                    /* user@host << */
  1761.                     case '$':                    /* user@host <$ */
  1762.                         state = ERROR_STATE ;
  1763.                         break ;
  1764.                     default:
  1765.                         if (!isspace(*cp)) {
  1766.                             from = cp ;
  1767.                             fromlen++ ;
  1768.                             state = IN_FROM ;
  1769.                         }
  1770.                 }
  1771.                 break ;
  1772.             case IN_FROM:
  1773.                 switch (*cp) {
  1774.                     case '\0':
  1775.                         state = FINAL_STATE ;        /* user@host <foo */
  1776.                         break ;
  1777.                     case '<':
  1778.                         state = ERROR_STATE ;        /* user@host <foo< */
  1779.                         break ;
  1780.                     case '$':
  1781.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1782.                         break ;
  1783.                     default:
  1784.                         if (isspace(*cp))
  1785.                             state = AFTER_FROM ;
  1786.                         else
  1787.                             fromlen++ ;
  1788.                 }
  1789.                 break ;
  1790.             case AFTER_FROM:
  1791.                 switch (*cp) {
  1792.                     case '\0':
  1793.                         state = FINAL_STATE ;        /* user@host <foo */
  1794.                         break ;
  1795.                     case '@':                        /* user@host <foo @ */
  1796.                     case '<':                        /* user@host <foo < */
  1797.                         state = ERROR_STATE ;
  1798.                         break ;
  1799.                     case '$':
  1800.                         state = LOOK_FOR_MSGID ;    /* user@host <foo $ */
  1801.                         break ;
  1802.                     default:
  1803.                         if (!isspace(*cp))
  1804.                             state = ERROR_STATE ;    /* user@host foo */
  1805.                 }
  1806.                 break ;
  1807.             case LOOK_FOR_MSGID:
  1808.                 if (*cp == '\0')
  1809.                     state = ERROR_STATE ;            /* msgid = $? */
  1810.                 else if (isspace(*cp))
  1811.                     state = ERROR_STATE ;            /* user@host <foo $ bar */
  1812.                 else {
  1813.                     msgid = cp ;
  1814.                     msgidlen++ ;
  1815.                     state = IN_MSGID ;
  1816.                 }
  1817.                 break ;
  1818.             case IN_MSGID:
  1819.                 if (*cp == '\0')
  1820.                     state = FINAL_STATE ;
  1821.                 else if (isspace(*cp))
  1822.                     state = FINAL_STATE ;
  1823.                 else
  1824.                     msgidlen++ ;
  1825.                 break ;
  1826.             default:
  1827.                 /* what are we doing in this state? */
  1828.                 state = ERROR_STATE ;
  1829.         }
  1830.     }
  1831.  
  1832.     if (state == ERROR_STATE)
  1833.         return -1 ;        /* syntax error */
  1834.  
  1835.     if ((m->to = malloc((unsigned)(userlen + hostlen + 2))) == NULLCHAR)
  1836.         return -1 ;        /* no room for to address */
  1837.  
  1838.     strncpy(m->to, user, userlen) ;
  1839.     m->to[userlen] = '\0' ;
  1840.     
  1841.     if (hostlen) {
  1842.         m->to[userlen] = '@' ;
  1843.         strncpy(m->to + userlen + 1, host, hostlen) ;
  1844.         m->to[userlen + hostlen + 1] = '\0' ;
  1845.     }
  1846.  
  1847.     if (fromlen) {
  1848.         if ((m->tofrom = malloc((unsigned)(fromlen + 1))) == NULLCHAR) {
  1849.             free(m->to) ;
  1850.             m->to = NULLCHAR ;
  1851.             return -1 ;
  1852.         }
  1853.         strncpy(m->tofrom, from, fromlen) ;
  1854.         m->tofrom[fromlen] = '\0' ;
  1855.     }
  1856.  
  1857.     if (msgidlen) {
  1858.         if ((m->tomsgid = malloc((unsigned)(msgidlen + 1))) == NULLCHAR) {
  1859.             free(m->to) ;
  1860.             m->to = NULLCHAR ;
  1861.             if (fromlen) {
  1862.                 free(m->tofrom) ;
  1863.                 m->tofrom = NULLCHAR ;
  1864.             }
  1865.             return -1 ;
  1866.         }
  1867.         strncpy(m->tomsgid, msgid, msgidlen) ;
  1868.         m->tomsgid[msgidlen] = '\0' ;
  1869.     }
  1870.     
  1871.     return 0 ;
  1872. }
  1873.  
  1874. /* This opens the data file and writes the mail header into it.
  1875.  * Returns 0 if OK, and -1 if not.
  1876.  */
  1877.  
  1878. static
  1879. mbx_data(m)
  1880. struct mbx *m ;
  1881. {
  1882.     time_t t, time() ;
  1883.     char *ptime() ;
  1884.     extern char hostname[] ;
  1885.     extern FILE *tmpfile();
  1886.     extern long get_msgid() ;
  1887.     
  1888.     if ((m->tfile = tmpfile()) == NULLFILE)
  1889.         return -1 ;
  1890.  
  1891.     time(&t) ;
  1892.     fprintf(m->tfile,"Date: %s",ptime(&t)) ;
  1893.     if (m->tomsgid)
  1894.         fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
  1895.     else
  1896.         fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
  1897.     fprintf(m->tfile,"From: %s%%%s.bbs@%s\n",
  1898.             m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
  1899.     fprintf(m->tfile,"To: %s\n",m->to) ;
  1900.     fprintf(m->tfile,"Subject: %s\n",m->line) ;
  1901.     if (m->stype != ' ')
  1902.         fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
  1903.     fprintf(m->tfile,"\n") ;
  1904.     
  1905.     return 0 ;
  1906. }
  1907.  
  1908. /* Shut down the mailbox communications connection */
  1909.  
  1910. static void
  1911. mbx_disc(m)
  1912. struct mbx *m ;
  1913. {
  1914.     switch (m->type) {
  1915.       case MBX_AX25:
  1916.         disc_ax25(m->cb.ax25_cb) ;
  1917.         break ;
  1918.       case MBX_NETROM:
  1919.           disc_nr4(m->cb.nr4_cb) ;
  1920.         break ;
  1921.     }
  1922. }
  1923. #endif /* XOBBS */
  1924.